﻿using Gnivc.CarDealership.Api.Application.Abstractions.Repositories;
using Gnivc.CarDealership.Api.Application.Dtos;
using Gnivc.CarDealership.Api.Domain.Entities;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace Gnivc.CarDealership.Api.Controllers;

[Route("api/[controller]")]
public class ReservationsController : ApiController
{
    private readonly IReservationRepository _reservationRepository;
    private readonly IUserRepository _userRepository;
    private readonly IVehicleRepository _vehicleRepository;

    public ReservationsController(
        IReservationRepository reservationRepository, 
        IUserRepository userRepository, 
        IVehicleRepository vehicleRepository)
    {
        _reservationRepository = reservationRepository;
        _userRepository = userRepository;
        _vehicleRepository = vehicleRepository;
    }

    [HttpGet("{vehicleId}")]
    public async Task<IResult> GetReservationsByVehicle(Guid vehicleId)
    {
        var getReservationsResult = 
            await _reservationRepository.GetAllByVehicle(vehicleId);

        if(getReservationsResult.IsError)
            return Problem(getReservationsResult.Errors);

        var reservations = getReservationsResult.Value!;

        return Results.Ok(reservations.Select(r => new ReservationDto
        {
            VehicleId = r.VehicleId,
            UserId = r.UserId,
            StartDate = r.StartDate,
            EndDate = r.EndDate,
            UserText = r.User.Name
        }));
    }

    [HttpPost("create")]
    public async Task<IResult> CreateReservation(
        [FromQuery] Guid vehicleId,
        [FromQuery] Guid userId)
    {
        var getUserResult = await _userRepository.GetByIdAsync(userId);

        if (getUserResult.IsError)
            return Problem(getUserResult.Errors);

        var getVehicleResult = await _vehicleRepository.GetByIdAsync(vehicleId);

        if(getVehicleResult.IsError)
            return Problem(getVehicleResult.Errors);

        var reservation = new Reservation(
            Guid.NewGuid(), 
            getVehicleResult.Value!, 
            getUserResult.Value!);

        var addResult = await _reservationRepository.AddAsync(reservation);

        if(addResult.IsError)
            return Problem(addResult.Errors);

        return Results.Ok(new ReservationDto
        {
            VehicleId = reservation.VehicleId,
            UserId = reservation.UserId,
            StartDate = reservation.StartDate,
            EndDate = reservation.EndDate,
            UserText = reservation.User.Name
        });
    }

    [HttpPost("cancel")]
    public async Task<IResult> CancelReservation([FromQuery] Guid reservationId)
    {
        var getReservationResult = await _reservationRepository.GetByIdAsync(reservationId);

        if (getReservationResult.IsError)
            return Problem(getReservationResult.Errors);

        var reservation = getReservationResult.Value!;

        reservation.EndDate = DateTime.UtcNow;

        var updateReservationResult = await _reservationRepository.UpdateAsync(reservation);
        
        if(updateReservationResult.IsError)
            return Problem(updateReservationResult.Errors);

        return Results.Ok(new { reservation.EndDate });
    }
}
